package game.engine;


import game.userinteraction.UserInputHandler;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.io.File;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;
import javax.swing.JPanel;


/**
 * 
 * This class is the surface the game will be drawn on. It also controls the
 * highest level of game flow
 * including the FPS and level progression.
 * 
 * @author Ben Schwab
 * 
 */
@SuppressWarnings("serial")
public abstract class GameController extends JPanel implements Runnable {

    /**
     * 
     * @param gameSurface
     */
    public static final int GAME_FPS = 30;
    /**
     * Delay time.
     */
    private final int myDelay = 1000 / GAME_FPS;
    private List<GameLevel> myGameLevels = new ArrayList<GameLevel>();
    private int myCurrentLevelPosition;
    private GameLevel myCurrentLevel;
    private boolean myIsRunning;
    private Queue<String> myUserActions = new LinkedList<String>();
    private Thread myGameLoop;
    private UserInputHandler myInputHandler;

    /**
     * Creates a gameLevel
     * @param inputHandler Input handler we will be using.
     */
    public GameController (UserInputHandler inputHandler) {
        setDoubleBuffered(true);
        myInputHandler = inputHandler;
        //createLevels(levelResources);
        myGameLoop = new Thread(this);

    }

    /**
     * Fills myGameLevels with gameLevels -- typically will call level creating
     * with all level files
     * in some resource folder.
     * @param levelResources File to load.
     */
    @SuppressWarnings("unused")
    private void createLevels (File levelResources) {
        //for every file in a resource folder create level
    };



    /**
     * Paint the board by telling Update active level
     * @param g Graphics used to draw.
     */
    @Override
    public void paint (Graphics g) {
        Graphics2D pen = (Graphics2D) g;
        myCurrentLevel.updateAndPaint(pen, myUserActions);
        myUserActions.clear();
    }

    /**
     * Show the user some game over message.
     */
    public abstract void showGameOver ();

    /**
     * Load the next level of the game.
     */
    public void loadNextLevel () {
        if (myCurrentLevelPosition + 1 == myGameLevels.size()) {
            gameWinMessage();
        }
        else {
            myCurrentLevel = myGameLevels.get(myCurrentLevelPosition + 1);
            myCurrentLevelPosition++;
        }
    }

    /**
     * Load an arbitrary level
     * 
     * @param level from level list to load
     */
    public void loadLevel (int level) {
        myCurrentLevel = myGameLevels.get(level);
        myCurrentLevelPosition = level;
    }

    /**
     * Loads a set of levels into the game.
     * @param levels Set of levels to load into the game.
     */
    public void setGameLevels(List<GameLevel> levels) {
        myGameLevels = levels;
    }

    /**
     * Display a message that states the game has been won.
     */
    public abstract void gameWinMessage ();

    /**
     * Starts the JPanel's animation thread
     */
    public void startGame () {
        if (!myIsRunning) {
            myGameLoop.start();
            myIsRunning = true; 
        }
    }

    /**
     * Pause the game thread.
     */
    @SuppressWarnings("deprecation")
    public void pauseGame () {
        if (myIsRunning) {
            myGameLoop.stop();
            myIsRunning = false;
        }
    };

    /**
     * Repaints this Jpanel at a constant rate - this repaint will cause a chain
     * of updates throughout the framework.
     */
    @Override
    public void run () {
        long beforeTime;
        long timeDiff;
        long sleep;
        beforeTime = System.currentTimeMillis();
        while (true) {
            repaint();
            timeDiff = System.currentTimeMillis() - beforeTime;
            sleep = myDelay - timeDiff;
            if (sleep < 0) {
                sleep = 2;
            }
            try {
                Thread.sleep(sleep);
            }
            catch (InterruptedException e) {
                System.out.println("interrupted");
            }

            beforeTime = System.currentTimeMillis();
        }

    }
    /**
     * 
     * @return Gets the input handler.
     */
    public UserInputHandler getInputHanlder() {
        return myInputHandler;
    }

}
